package com.oraycn.esbasic.helpers;

import android.os.Build;
import android.support.annotation.RequiresApi;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

/**
 * token sm4解密工具类
 */
public class EncryptHelper {


    //region SM4   需引用 implementation 'org.bouncycastle:bcmail-jdk15on:1.66'
//    private static final String PADDING_MODE = "SM4/ECB/PKCS5Padding";
//
//    private static final String FILE_MODE_READ = "r";
//
//    private static final String FILE_MODE_READ_WRITE = "rw";
//
//    private static final String PBK_SHA1 = "PBKDF2WithHmacSHA1";
//
//    private static final String ALGORITHM_SM4 = "SM4";
//
//    private static final int KEY_DEFAULT_SIZE = 128;
//
//    private static final int ENCRYPT_BUFFER_SIZE = 1024;
//
//    private static final int DECRYPT_BUFFER_SIZE = 1040;
//
//    static {
//        try {
//            Security.addProvider(new BouncyCastleProvider());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 大字符串分段加密
//     *
//     * @param content 需要加密的内容
//     * @param seed    种子
//     * @return 加密后内容
//     * @throws Exception 异常
//     */
//    @RequiresApi(api = Build.VERSION_CODES.O)
//    public static String sm4EncryptLarge(String content, String seed) throws Exception {
//        byte[] data = content.getBytes(StandardCharsets.UTF_8);
//        byte[] rawKey = getRawKey(seed);
//        Cipher mCipher = generateEcbCipher(Cipher.ENCRYPT_MODE, rawKey);
//        int inputLen = data.length;
//        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        int offSet = 0;
//        byte[] cache;
//        int i = 0;
//        // 对数据分段解密
//        while (inputLen - offSet > 0) {
//            if (inputLen - offSet > ENCRYPT_BUFFER_SIZE) {
//                cache = mCipher.doFinal(data, offSet, ENCRYPT_BUFFER_SIZE);
//            } else {
//                cache = mCipher.doFinal(data, offSet, inputLen - offSet);
//            }
//            out.write(cache, 0, cache.length);
//            i++;
//            offSet = i * ENCRYPT_BUFFER_SIZE;
//        }
//        byte[] decryptedData = out.toByteArray();
//        out.close();
//        return Base64.getEncoder().encodeToString(decryptedData);
//    }
//
//    /**
//     * 大字符串分段解密
//     *
//     * @param content 密文
//     * @param seed    种子
//     * @return 解密后内容
//     * @throws Exception 异常
//     */
//    @RequiresApi(api = Build.VERSION_CODES.O)
//    public static String sm4DecryptLarge(String content, String seed) throws Exception {
//        byte[] data = Base64.getDecoder().decode(content);
//        byte[] rawKey = getRawKey(seed);
//        Cipher mCipher = generateEcbCipher(Cipher.DECRYPT_MODE, rawKey);
//        int inputLen = data.length;
//        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        int offSet = 0;
//        byte[] cache;
//        int i = 0;
//        // 对数据分段解密
//        while (inputLen - offSet > 0) {
//            if (inputLen - offSet > DECRYPT_BUFFER_SIZE) {
//                cache = mCipher.doFinal(data, offSet, DECRYPT_BUFFER_SIZE);
//            } else {
//                cache = mCipher.doFinal(data, offSet, inputLen - offSet);
//            }
//            out.write(cache, 0, cache.length);
//            i++;
//            offSet = i * DECRYPT_BUFFER_SIZE;
//        }
//        byte[] decryptedData = out.toByteArray();
//        out.close();
//        return new String(decryptedData, StandardCharsets.UTF_8);
//    }
//
//    /**
//     * 字符串加密
//     *
//     * @param data 字符串
//     * @param seed 种子
//     * @return 加密后内容
//     * @throws Exception 异常
//     */
//    public static String sm4Encrypt(String data, String seed) throws Exception {
//        byte[] rawKey = getRawKey(seed);
//        Cipher mCipher = generateEcbCipher(Cipher.ENCRYPT_MODE, rawKey);
//        byte[] bytes = mCipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
//        return Hex.toHexString(bytes);
//    }
//
//    /**
//     * 字符串解密
//     *
//     * @param data 加密字符串
//     * @param seed 种子
//     * @return 解密后内容
//     * @throws Exception 异常
//     */
//    public static String sm4Decrypt(String data, String seed) throws Exception {
//        byte[] rawKey = getRawKey(seed);
//        Cipher mCipher = generateEcbCipher(Cipher.DECRYPT_MODE, rawKey);
//        byte[] bytes = mCipher.doFinal(Hex.decode(data));
//        return new String(bytes, StandardCharsets.UTF_8);
//    }
//
//    /**
//     * 使用一个安全的随机数来产生一个密匙,密匙加密使用的
//     *
//     * @param seed 种子
//     * @return 随机数组
//     * @throws NoSuchAlgorithmException 模式错误
//     */
//    public static byte[] getRawKey(String seed) throws NoSuchAlgorithmException, InvalidKeySpecException {
//        return seed.getBytes();
////            int count = 1000;
////            int keyLen = KEY_DEFAULT_SIZE;
////            int saltLen = keyLen / 8;
////            SecureRandom random = new SecureRandom();
////            byte[] salt = new byte[saltLen];
////            random.setSeed(seed.getBytes());
////            random.nextBytes(salt);
////            KeySpec keySpec = new PBEKeySpec(seed.toCharArray(), salt, count, keyLen);
////            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(PBK_SHA1);
////            return secretKeyFactory.generateSecret(keySpec).getEncoded();
//    }
//
//    private static BouncyCastleProvider provider = new BouncyCastleProvider();
//
//    /**
//     * 生成ecb模式密码工具
//     *
//     * @param mode 模式
//     * @param key  密钥
//     * @return 密码工具
//     * @throws Exception 异常
//     */
//    private static Cipher generateEcbCipher(int mode, byte[] key) throws Exception {
//        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
//        Security.addProvider(provider);
//        Cipher cipher = Cipher.getInstance(PADDING_MODE, BouncyCastleProvider.PROVIDER_NAME);
//        Key sm4Key = new SecretKeySpec(key, ALGORITHM_SM4);
//        cipher.init(mode, sm4Key);
//        return cipher;
//    }
    //endregion


    //region DES

    /**
     * @param source 编码内容
     * @param key    密钥
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String encrypt_des(String source, String key) {
        String encrypt = null;
        try {
            byte[] ret = encrypt(source.getBytes("utf-8"), key);
            encrypt = new String(Base64.getEncoder().encode(ret));
        } catch (Exception e) {
            e.printStackTrace();
            encrypt = null;
        }
        return encrypt;
    }

    /**
     * @param encryptedData 解码内容
     * @param key           密钥
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String decrypt_des(String encryptedData, String key) {
        String descryptedData = null;
        try {
            byte[] ret = descrypt(Base64.getDecoder().decode(encryptedData.getBytes()), key);
            descryptedData = new String(ret, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            descryptedData = null;
        }
        return descryptedData;
    }

    private static byte[] encrypt(byte[] primaryData, String key) {
        Key desKey = setKey(key);
        try {
            Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成加密操作
            cipher.init(Cipher.ENCRYPT_MODE, desKey); // 用密钥初始化Cipher对象(加密)
            return cipher.doFinal(primaryData);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static byte[] descrypt(byte[] encryptedData, String key) {
        Key desKey = setKey(key);
        try {
            Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成解密操作
            cipher.init(Cipher.DECRYPT_MODE, desKey); // 用密钥初始化Cipher对象(解密)
            return cipher.doFinal(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Key setKey(String strKey) {

        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(strKey.getBytes("utf-8"), "DES");
            return secretKeySpec;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
//      测试使用
//    public static void main(String[] args) {
//        String code = "hello world";
//        String key = "key";
//        String unicode = "utf-8";
//        String encrypt = MyDes.encrypt(code, key, unicode);
//        String decrypt = MyDes.decrypt(encrypt, key, unicode);
//        System.out.println("原内容：" + code);
//        System.out.println("加密：" + encrypt);
//        System.out.println("解密：" + decrypt);
//    }
    //endregion


}